package com.shuai.AI.ai_app.config;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/** Redis配置 - 使用Fastjson2并加强安全防护 */
@Slf4j
@Configuration
public class RedisConfig {

  /** 创建安全的白名单过滤器 只允许反序列化指定的安全包路径下的类 */
  private JSONReader.AutoTypeBeforeHandler createSafeFilter() {
    return new JSONReader.AutoTypeBeforeHandler() {
      @Override
      public Class<?> apply(String typeName, Class<?> expectClass, long features) {
        if (typeName == null) {
          return null;
        }
        // 只允许反序列化指定的安全包路径下的类
        boolean accepted =
            typeName.startsWith("com.shuai.AI.")
                || typeName.startsWith("java.util.")
                || typeName.startsWith("org.springframework.ai.chat.messages.")
                || typeName.startsWith("com.shuai.AI.chatmemory.SerializableMessage");

        // 添加日志，方便调试

        log.info("Checking class: " + typeName + ", Accepted: " + accepted);

        if (accepted) {
          try {
            return Class.forName(typeName);
          } catch (ClassNotFoundException e) {
            log.error("Class not found: " + typeName, e);
            return null;
          }
        }
        return null;
      }
    };
  }

  /** 创建安全的Fastjson2序列化器 */
  @Bean
  public RedisSerializer<Object> fastJson2JsonRedisSerializer() {
    // 安全的写配置（序列化配置）
    JSONWriter.Feature[] writeFeatures = {
      // 自动写入类名信息，确保反序列化时能正确识别对象类型
      JSONWriter.Feature.WriteClassName,

      // 将枚举序列化为其名称（而非序号），提高可读性和稳定性
      JSONWriter.Feature.WriteEnumsUsingName,

      // 支持大对象序列化，优化处理大型数据结构的性能
      JSONWriter.Feature.LargeObject
    };

    // 安全的读配置（反序列化配置）
    JSONReader.Feature[] readFeatures = {
      // 在严格的白名单控制下启用AutoType功能，允许根据类名自动识别类型
      // 注意：必须配合白名单过滤器使用，否则存在安全风险
      JSONReader.Feature.SupportAutoType,

      // 使用原生对象而非包装对象，提高性能和减少内存占用
      JSONReader.Feature.UseNativeObject,

      // 基于字段而非getter/setter方法进行反序列化，提高兼容性和性能
      // 此特性使Fastjson2直接通过反射访问类的字段进行赋值，而不是调用setter方法
      // 工作方式：
      // 1. 直接通过反射访问类的字段（包括私有字段）
      // 2. 跳过setter方法的调用，直接为字段赋值
      // 3. 提高兼容性：即使类没有提供setter方法也能正确反序列化
      // 4. 注意事项：可能会绕过setter方法中的验证逻辑，需要确保数据安全性
      //      JSONReader.Feature.FieldBased
    };

    // 创建安全的序列化器
    return new RedisSerializer<Object>() {

      @Override
      public byte[] serialize(Object object) throws SerializationException {
        if (object == null) {
          return new byte[0];
        }
        try {
          // 序列化时自动写入类名，无需手动指定Feature
          byte[] bytes = JSON.toJSONBytes(object, writeFeatures); // 使用指定的序列化配置
          // 临时打印日志，查看序列化后的字符串内容（注意日志级别）
          //          log.info("Serialized JSON: {}", new String(bytes, StandardCharsets.UTF_8));
          return bytes;
        } catch (Exception e) {
          throw new SerializationException("Could not serialize: " + e.getMessage(), e);
        }
      }

      private final Filter autoTypeFilter = createSafeFilter();

      @Override
      public Object deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
          return null;
        }
        try {

          // 反序列化时使用严格的白名单过滤
          Object parsedObject =
              JSON.parseObject(
                  bytes,
                  Object.class,
                  autoTypeFilter, // 应用白名单过滤器
                  readFeatures); // 使用指定的反序列化配置
          // 临时打印日志，查看反序列化后的对象内容（注意日志级别）
          //          log.info("Deserialized Object: {}", parsedObject);
          return parsedObject;
        } catch (Exception e) {
          throw new SerializationException("Could not deserialize: " + e.getMessage(), e);
        }
      }
    };
  }

  @Bean
  public RedisTemplate<Object, Object> redisTemplate(
      RedisConnectionFactory redisConnectionFactory,
      RedisSerializer<Object> fastJson2JsonRedisSerializer) {

    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(redisConnectionFactory);

    // 使用StringRedisSerializer来序列化和反序列化redis的key值
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

    // 设置序列化规则
    redisTemplate.setKeySerializer(stringRedisSerializer);
    redisTemplate.setHashKeySerializer(stringRedisSerializer);
    redisTemplate.setValueSerializer(fastJson2JsonRedisSerializer);
    redisTemplate.setHashValueSerializer(fastJson2JsonRedisSerializer);

    // 可选：根据需要决定是否启用事务支持
    // redisTemplate.setEnableTransactionSupport(true);

    redisTemplate.afterPropertiesSet();
    return redisTemplate;
  }
}
